import { WeaveArchive, type Artifact } from "@/components/weave-archive";
import { api } from "@/lib/api";
import type { DecisionDto, SnapshotDto } from "@/lib/types";
export const dynamic = "force-dynamic";
/**
* Everything this repo has woven, in one ledger.
*
* The other pages each show one kind of thing. This shows the whole bolt —
* snapshots, the source inside them, decisions, the attestations that settled
* them, and the refs pointing at any of it — in the order it was made, with
* provenance as the axis you sort and filter by.
*
* Assembled across every ref rather than the default one, because history
* that only exists on a branch is still history.
*/
export default async function WeavePage({
params,
}: {
params: Promise<{ repo: string }>;
}) {
const { repo } = await params;
const detail = await api.repo(repo);
// Walk every ref; a snapshot reachable from two refs is still one artifact.
const logs = await Promise.all(
detail.refs.map((r) =>
api
.log(repo, r.name, 200)
.then((l) => ({ ref: r.name, entries: l.entries }))
.catch(() => ({ ref: r.name, entries: [] as SnapshotDto[] })),
),
);
const snapshots = new Map<string, SnapshotDto>();
const refsBySnapshot = new Map<string, string[]>();
for (const { ref, entries } of logs) {
for (const s of entries) snapshots.set(s.id, s);
}
for (const r of detail.refs) {
const at = refsBySnapshot.get(r.head) ?? [];
at.push(r.name);
refsBySnapshot.set(r.head, at);
}
const decisions: DecisionDto[] = await api
.decisions(repo)
.then((d) => d.decisions)
.catch(() => []);
const artifacts: Artifact[] = [];
for (const s of snapshots.values()) {
artifacts.push({
kind: "snapshot",
id: s.id,
short: s.short,
at: s.at,
title: s.message,
provenance: s.provenance,
actor: s.author,
refs: refsBySnapshot.get(s.id) ?? [],
parents: s.parents,
tree: s.tree,
});
}
for (const d of decisions) {
artifacts.push({
kind: "decision",
id: d.id,
short: d.short,
at: d.at,
title: d.title,
// A decision is a machine's or a person's *proposal*; it carries the
// proposer's hand, never an attestation's.
provenance: d.proposed_by.kind === "human" ? "human" : "agent",
actor: d.proposed_by,
rationale: d.rationale,
families: d.families,
scope: d.scope,
state: d.state,
});
if (d.attestation) {
artifacts.push({
kind: "attestation",
id: d.attestation.id,
short: d.attestation.id.slice(0, 12),
at: d.attestation.at,
title: d.title,
provenance: "human",
actor: d.attestation.attestor,
statement: d.attestation.statement,
decision: d.id,
});
}
}
artifacts.sort((a, b) => b.at - a.at || a.id.localeCompare(b.id));
return (
<WeaveArchive
repo={repo}
artifacts={artifacts}
objectCount={detail.object_count}
refs={detail.refs}
/>
);
}